package org.ims.inv.web.action;

import java.math.BigInteger;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.ims.inv.model.conference.ModelConference;
import org.ims.inv.model.flow.material.ModelFlowMaterial;
import org.ims.inv.model.project.ModelProject;
import org.ims.inv.model.project.ModelProjectProcess;
import org.ims.inv.model.system.ModelAppDictionary;
import org.ims.inv.model.system.ModelAppRole;
import org.ims.inv.model.system.ModelAppUser;
import org.ims.inv.service.base.ServiceBase;
import org.ims.inv.service.flow.ServiceWorkFlow;
import org.ims.inv.service.system.ServiceAppDictionary;
import org.ims.inv.service.system.ServiceAppLog;
import org.ims.inv.service.system.ServiceAppProjectGroup;
import org.ims.inv.service.system.ServiceAppRole;
import org.ims.inv.service.system.ServiceAppUser;
import org.ims.inv.service.system.ServiceAppUserProfile;
import org.ims.inv.web.util.ContextUtil;

import cn.trymore.core.exception.ServiceException;
import cn.trymore.core.util.UtilCollection;
import cn.trymore.core.util.UtilString;
import cn.trymore.core.web.action.BaseAction;
import cn.trymore.core.web.push.MessagePush;
import cn.trymore.oa.service.system.ServiceFileAttach;

/**
 * Action: 系统业务基类
 * 
 * @author Jeccy.Zhao
 *
 */
public class BaseAppAction
extends BaseAction
{
	/**
	 * The LOGGER
	 */
	private static final Logger LOGGER = Logger.getLogger(BaseAppAction.class);
	
	/**
	 * 消息更新Script
	 */
	protected static final String scriptMessageNotify = "messageNotify";
	
	/**
	 * 短消息页面元素ID
	 */
	protected static final String scriptArgMessageKey = "elenum_msg";
	
	/**
	 * The application role service.
	 */
	@Resource
	protected ServiceAppRole serviceAppRole;
	
	/**
	 * The application user service.
	 */
	@Resource
	protected ServiceAppUser serviceAppUser;
	
	/**
	 * The application user profile service
	 */
	@Resource
	protected ServiceAppUserProfile serviceAppUserProfile;
	
	/**
	 * The application dictionary service
	 */
	@Resource
	protected ServiceAppDictionary serviceAppDictionary;
	
	/**
	 * The application log service
	 */
	@Resource
	protected ServiceAppLog serviceAppLog;
	
	/**
	 * The service of work flow
	 */
	@Resource
	protected ServiceWorkFlow serviceWorkFlow;
	
	/**
	 * The service of project group
	 */
	@Resource
	protected ServiceAppProjectGroup serviceAppProjectGroup;
	
	/**
	 * The service of file
	 */
	@Resource
	protected ServiceFileAttach serviceFileAttach;
	
	/**
	 * The service of HRM employee develop.
	 */
	@Resource
	protected ServiceBase serviceBase;
	
	/**
	 * The message push bean
	 */
	@Resource
	protected MessagePush messagePush;
	
	/**
	 * Obtains all role entities
	 * 
	 * @return list of role entities
	 * @throws ServiceException 
	 */
	protected List<ModelAppRole> getAllRoles() throws ServiceException
	{
		return this.serviceAppRole.getAllRoles();
	}
	
	/**
	 * Obtains all dictionaries
	 * 
	 * @param dictType
	 * @return
	 * @throws ServiceException
	 */
	protected List<ModelAppDictionary> getDictionariesByType (String dictType) throws ServiceException
	{
		return this.serviceAppDictionary.getByType(dictType);
	}
	
	/**
	 * <b>[WebAction]</b> 
	 * <br/>
	 * 加载材料区数据
	 */
	protected List<ModelFlowMaterial> loadRootFlowMaterial (String formNo) throws ServiceException
	{
		try
		{
			if (UtilString.isNotEmpty(formNo))
			{
				// TODO
				return null;
			}
			else
			{
				return this.serviceWorkFlow.getServiceFlowMaterial().getAllRootMaterials();
			}
		}
		catch (ServiceException e)
		{
			throw new ServiceException(e);
		}
	}
	
	/**
	 * 根据用户名或用户编号搜索用户并自动提示
	 * 
	 * @param userName
	 * @return
	 */
	public ActionForward actionViewDocOnline (ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
	{
		this.outWriteAllParameters(request);
		
		return mapping.findForward("doc.online");
	}
	
	/**
	 * 根据用户名或用户编号搜索用户并自动提示
	 * 
	 * @param userName
	 * @return
	 */
	public ActionForward lookupUserByName (ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
	{
		String search = request.getParameter("search");
		
		try
		{
			StringBuilder builder = new StringBuilder();
			List<ModelAppUser> result = this.serviceAppUser.findByUserNameORUserNo(search);
			if (result != null && result.size() > 0)
			{
				int count = 0;
				for (ModelAppUser user : result)
				{
					count++;
					
					if (!user.isSuperUser() && user.getUserStatus().equals(ModelAppUser.STAT_NORMAL))
					{
						builder.append("{");
						builder.append("\"id\":\"" + user.getId() + "\",");
						builder.append("\"username\":\"" + user.getUsername() + "\",");
						builder.append("\"userPhone\":\"" + user.getUserPhoneNumber() + "\",");
						builder.append("\"userNo\":\"" + user.getUserNo() + "\"");
						builder.append("}");
						
						if (count < result.size())
						{
							builder.append(",");
						}
					}
				}
				String callbackJson = "[" + builder.toString() + "]";
				return ajaxPrint(response, callbackJson);
			}
		} 
		catch (ServiceException e)
		{
			LOGGER.error("Exception raised when lookup user..", e);
		}
		
		return ajaxPrint(response, "[]");
	}
	
	/**
	 * 获取所有用户ID集合
	 * @return
	 */
	protected String getAllUserIds ()
	{
		StringBuilder builder = new StringBuilder();
		builder.append(ModelAppUser.SUPER_USER_ID.toString());
		try
		{
			List<ModelAppUser> users = this.serviceAppUser.getAll();
			if (UtilCollection.isNotEmpty(users))
			{
				for (ModelAppUser user : users)
				{
					builder.append("," + user.getId());
				}
			}
		} 
		catch (ServiceException e)
		{
			LOGGER.error("Exception raised when fetching all user ids.", e);
		}
		
		return builder.toString();
	}
	
	/**
	 * 获取所有用户ID集合
	 * 
	 * @param roleKey
	 * @return
	 */
	protected String getAllUserIdsByRole (String roleKey)
	{
		StringBuilder builder = new StringBuilder();
		builder.append(ModelAppUser.SUPER_USER_ID.toString());
		try
		{
			List<ModelAppUser> users = this.serviceAppUser.findByUserRole(roleKey);
			if (UtilCollection.isNotEmpty(users))
			{
				for (ModelAppUser user : users)
				{
					builder.append("," + user.getId());
				}
			}
		} 
		catch (ServiceException e)
		{
			LOGGER.error("Exception raised when fetching all user ids.", e);
		}
		
		return builder.toString();
	}
	
	/**
	 * 将UID字符串集转换成JSON对象
	 * 
	 * @param ids
	 * @param separtor
	 * @return
	 */
	protected String converseUidsToObject (String ids, String separtor)
	{
		StringBuilder builder = new StringBuilder();
		
		builder.append("[");
		
		if (UtilString.isNotEmpty(ids))
		{
			String[] lstId = ids.split(separtor);
			for (String uid : lstId)
			{
				try
				{
					if (UtilString.isNotEmpty(uid))
					{
						ModelAppUser user = this.serviceAppUser.get(uid);
						if (user != null)
						{
							builder.append("{");
							builder.append("\"id\":" + uid + ",");
							builder.append("\"username\":\"" + user.getUsername() + "\"");
							builder.append("}");
							builder.append(",");
						}
					}
				}
				catch (Exception e)
				{
					LOGGER.error("Entity can not be found with id:" + uid, e);
				}
			}
		}
		
		builder.append("{}");
		builder.append("]");
		
		return builder.toString();
	}
	
	/**
	 * 获取待提交材料项目数
	 * 
	 * @return
	 */
	protected BigInteger getNumProjectForPost ()
	{
		return this.serviceBase.getCountByNativeSql(
				"select count(*) from app_project p " +
				"where p.p_currentProcess IS NOT NULL and p.p_status = " + ModelProject.EProjectStatus.TOPOST.getValue() +
				" and (p.p_manager = " + ContextUtil.getCurrentUser().getId() + 
				" or FIND_IN_SET(" + ContextUtil.getCurrentUser().getId()+ ", p.p_attendee_ids) > 0)");
	}

	/**
	 * 获取审批中项目数
	 * 
	 * @return
	 */
	protected BigInteger getNumProjectForApproving ()
	{
		return this.serviceBase.getCountByNativeSql(
				"select count(*) from app_project p " +
				"where p.p_status = " + ModelProject.EProjectStatus.APPROVING.getValue() + 
				" and (p.p_manager = " + ContextUtil.getCurrentUser().getId() + 
				" or FIND_IN_SET(" + ContextUtil.getCurrentUser().getId()+ ", p.p_attendee_ids) > 0)");
	}
	
	/**
	 * 获取审批项目数
	 * 
	 * @return
	 */
	protected BigInteger getNumProjectForTrailAudit ()
	{
		return this.serviceBase.getCountByNativeSql(
				"select count(*) from app_project p " +
				"left join app_project_process_form f on p.p_currentProcess = f.form_id " +
				"where f.seq_sn = 1 and p.p_status = " + ModelProject.EProjectStatus.APPROVING.getValue());
	}
	
	/**
	 * 获取需过会项目数
	 * 
	 * @return
	 */
	protected BigInteger getNumProjectForConference (String id)
	{
		return this.serviceBase.getCountByNativeSql(
				"select count(*) from app_project p " +
				"left join app_project_process_form f on p.p_currentProcess = f.form_id " +
				"where f.node_key = (select node_key from app_process_template where t_id = " + id + 
				") and f.material_status = " + ModelProjectProcess.EProjectMaterialStatus.POSTED.getValue() +
				" and (f.depend_flow IS NULL or " +
				" f.depend_flow_audit_status = " + ModelProjectProcess.EProjectDependFlowAuditState.PASS.getValue() + ")");
	}
	
	/**
	 * 获取过会预审数
	 * 
	 * @return
	 */
	protected BigInteger getNumProjectForConferenceAudit()
	{
		String sql = 
			"select count(*) from app_project_conference c " +
			"left join app_project_process_form f on c.form_id = f.form_id " +
			"where c.audit_status IS NULL ";
		
		if (!ContextUtil.getCurrentUser().isSuperUser())
		{
			sql += 
				"and f.depend_flow in " +
				"(select t_id from app_process_confer where " +
				"FIND_IN_SET(to_roleId, \"" + ContextUtil.getCurrentUser().getRoleId() + "\")" +
				//"to_roleId = " + ContextUtil.getCurrentUser().getRoleId() +
				")";
		}
		
		return this.serviceBase.getCountByNativeSql(sql);
	}
	
	/**
	 * 获取需要审批的会议数量
	 * 
	 * @return
	 */
	protected BigInteger getNumConferenceAudit ()
	{
		String sql = 
			"select count(*) from app_conference c where c.c_status = " + ModelConference.EConferenceStatus.AUDITING.getValue();
		
		String roleKey = ContextUtil.getCurrentUser().getRoleKey();
		if (roleKey.startsWith(ModelAppRole.ROLE_PROJECT_LEADER))
		{
			sql += " and c_leaderaudit = 1";
		}
		else if (roleKey.startsWith(ModelAppRole.ROLE_PROJECT_MASTER))
		{
			sql += " and c_leaderaudit = 0";
		}
		else if (roleKey.startsWith(ModelAppRole.ROLE_SUPER))
		{
			// do nothing.
		}
		else
		{
			return BigInteger.valueOf(0L);
		}
		
		return this.serviceBase.getCountByNativeSql(sql);
	}
	
	/**
	 * 获取需预审项目数
	 * 
	 * @return
	 */
	protected BigInteger getNumProjectForConferencePreAudit (String id)
	{
		return this.serviceBase.getCountByNativeSql(
				"select count(*) from app_project_conference c " +
				"left join app_project_process_form f on c.form_id = f.form_id " +
				"where c.audit_status IS NULL and f.depend_flow = " + id);
	}
	
	/**
	 * 获取复审项目数
	 * 
	 * @return
	 */
	protected BigInteger getNumProjectForReviewAudit ()
	{
		return this.serviceBase.getCountByNativeSql(
				"select count(*) from app_project p " +
				"left join app_project_process_form f on p.p_currentProcess = f.form_id " +
				"where f.seq_sn = 2 and p.p_status = " + ModelProject.EProjectStatus.APPROVING.getValue());
	}
	
	/**
	 * 获取过会项目数
	 * 
	 * @return
	 */
	protected BigInteger getNumProjectForConference ()
	{
		return this.serviceBase.getCountByNativeSql(
				"select count(*) from app_project p" +
				" left join app_project_process_form f on p.p_currentProcess = f.form_id" +
				" where f.seq_sn > 2 and p.p_status = " + ModelProject.EProjectStatus.APPROVING.getValue() + 
				" and f.material_status = " + ModelProjectProcess.EProjectMaterialStatus.POSTED.getValue() +
				" and (f.depend_flow IS NULL or " +
				" f.depend_flow_audit_status = " + ModelProjectProcess.EProjectDependFlowAuditState.PASS.getValue() + ")");
	}
	
	/**
	 * 获取项目分配项目数
	 * 
	 * @return
	 */
	protected BigInteger getNumProjectForAllocate ()
	{
		return
		this.serviceBase.getCountByNativeSql(
				"select count(*) from app_project p " +
				"where p.p_currentProcess is null and p.p_status = " + ModelProject.EProjectStatus.APPROVING.getValue());
	}
	
	/**
	 * 获取审批退回
	 * 
	 * @return
	 */
	protected BigInteger getNumProjectForReturn ()
	{
		return this.serviceBase.getCountByNativeSql(
				"select count(*) from app_project p " +
				"where p.p_status = " + ModelProject.EProjectStatus.RETURNED.getValue() + 
				" and (p.p_manager = " + ContextUtil.getCurrentUser().getId() + 
				" or FIND_IN_SET(" + ContextUtil.getCurrentUser().getId()+ ", p.p_attendee_ids) > 0)");
	}
	
	/**
	 * 初始化用户权限信息
	 * 
	 * @param user
	 */
	protected void initUserRole (ModelAppUser user)
	{
		if (user != null && !UtilCollection.isNotEmpty(user.getUserRoles()))
		{
			String roleIds = user.getUserRole();
			if (UtilString.isNotEmpty(roleIds))
			{
				String[] ids = roleIds.split(",");
				for (String roleId : ids)
				{
					if (!user.containsRole(roleId))
					{
						try
						{
							ModelAppRole role = this.serviceAppRole.get(roleId);
							if (role != null)
							{
								user.getUserRoles().add(role);
							}
						}
						catch (Exception e)
						{
							LOGGER.error("Error when fetching role: " + e);
						}
					}
				}
			}
		}
	}
	
	public static Logger getLogger()
	{
		return LOGGER;
	}

	public void setServiceAppRole(ServiceAppRole serviceAppRole)
	{
		this.serviceAppRole = serviceAppRole;
	}

	public ServiceAppRole getServiceAppRole()
	{
		return serviceAppRole;
	}

	public void setServiceAppUser(ServiceAppUser serviceAppUser)
	{
		this.serviceAppUser = serviceAppUser;
	}

	public ServiceAppUser getServiceAppUser()
	{
		return serviceAppUser;
	}

	public void setServiceAppDictionary(ServiceAppDictionary serviceAppDictionary)
	{
		this.serviceAppDictionary = serviceAppDictionary;
	}

	public ServiceAppDictionary getServiceAppDictionary()
	{
		return serviceAppDictionary;
	}

	public void setServiceAppLog(ServiceAppLog serviceAppLog)
	{
		this.serviceAppLog = serviceAppLog;
	}

	public ServiceAppLog getServiceAppLog()
	{
		return serviceAppLog;
	}

	public void setServiceWorkFlow(ServiceWorkFlow serviceWorkFlow)
	{
		this.serviceWorkFlow = serviceWorkFlow;
	}

	public ServiceWorkFlow getServiceWorkFlow()
	{
		return serviceWorkFlow;
	}

	public void setServiceFileAttach(ServiceFileAttach serviceFileAttach)
	{
		this.serviceFileAttach = serviceFileAttach;
	}

	public ServiceFileAttach getServiceFileAttach()
	{
		return serviceFileAttach;
	}

	public void setServiceBase(ServiceBase serviceBase)
	{
		this.serviceBase = serviceBase;
	}

	public ServiceBase getServiceBase()
	{
		return serviceBase;
	}

	public void setMessagePush(MessagePush messagePush)
	{
		this.messagePush = messagePush;
	}

	public MessagePush getMessagePush()
	{
		return messagePush;
	}

	public ServiceAppProjectGroup getServiceAppProjectGroup()
	{
		return serviceAppProjectGroup;
	}

	public void setServiceAppProjectGroup(ServiceAppProjectGroup serviceAppProjectGroup)
	{
		this.serviceAppProjectGroup = serviceAppProjectGroup;
	}

	public ServiceAppUserProfile getServiceAppUserProfile()
	{
		return serviceAppUserProfile;
	}

	public void setServiceAppUserProfile(ServiceAppUserProfile serviceAppUserProfile)
	{
		this.serviceAppUserProfile = serviceAppUserProfile;
	}
	
}
